﻿
namespace MathService.DSP
{
    /// <summary>Цифровой фильтр нижних частот (RC-цепочка)</summary>
    public class DigitalLowPassRCFilter : CBIH
    {

        /// <summary>Получить коэффициенты полинома знаменателя передаточной функции цифрового фильтра</summary>
        ///<param name="f0">Частота среза</param>
        ///<param name="dt">Частота дискретизации</param>
        /// <returns>Коэффициенты полинома a0 + a1 z^-1</returns>
        // a0 = 1 a1 = (1-2*tau/dt)/(1+2*tau/dt)
        private static double[] GetA(double f0, double dt)
        {
            var tau2 = 2 / (f0 * dt);
            return new[] { 1, (1 - tau2) / (1 + tau2) };
        }


        /// <summary>Получить коэффициенты полинома числителя передаточной функции цифрового фильтра</summary>
        ///<param name="f0">Частота среза</param>
        ///<param name="dt">Частота дискретизации</param>
        /// <returns>Коэффициенты полинома b0 + b1 z^-1</returns>
        // b0 = 1/(1+2*tau/dt) b1 = 1/(1+2*tau/dt)
        private static double[] GetB(double f0, double dt)
        {
            var b = 1 / (1 + 2 / (f0 * dt));
            return new[] { b, b };
        }

        /// <summary>Частота среза</summary>
        private double f_f0;
        /// <summary>Период дискретизации</summary>
        private double f_dt;

        /// <summary>Частота среза</summary>
        public double f0 { get { return f_f0; } set { if(!Equals(value, f_f0)) Initialize(value, f_dt); } }
        /// <summary>Период дискретизации</summary>
        public double dt { get { return f_dt; } set { if(!Equals(value, f_dt)) Initialize(f_f0, value); } }

        ///<summary>Цифровой фильтр нижних частот (RC-цепочка)</summary>
        ///<param name="f0">Частота среза</param>
        ///<param name="dt">Частота дискретизации</param>
        public DigitalLowPassRCFilter(double f0, double dt)
            : base(GetA(f0, dt), GetB(f0, dt))
        {
            f_f0 = f0;
            f_dt = dt;
        }

        ///<summary>Инициализация фильтра</summary>
        ///<param name="f0">Частота среза</param>
        ///<param name="dt">Частота дискретизации</param>
        public void Initialize(double f0, double dt) { Initialize(GetA(f_f0 = f0, f_dt = dt), GetB(f0, dt)); }
    }
}
